/* eslint-disable @typescript-eslint/no-explicit-any */
// eslint-disable-next-line import/consistent-type-specifier-style
import type {
  LazyComponent,
  Payload,
  PendingPayload,
  RejectedPayload,
  ResolvedPayload,
} from "./lazy-type";

const enum Status {
  Uninitialized = -1,
  Pending = 0,
  Resolved = 1,
  Rejected = 2,
}

declare const REACT_LAZY_TYPE: symbol | number; // Assume this is defined elsewhere
declare const disableDefaultPropsExceptForClasses: boolean; // Assume this is defined
declare const __DEV__: boolean; // Environment flag

function lazyInitializer<T>(payload: Payload<T>): T {
  if (payload._status === Status.Uninitialized) {
    const ctor = payload._result;
    const thenable = ctor();

    thenable.then(
      (moduleObject) => {
        if (
          (payload as Payload<T>)._status === Status.Pending ||
          payload._status === Status.Uninitialized
        ) {
          const resolved = payload as unknown as ResolvedPayload<T>;
          resolved._status = Status.Resolved;
          resolved._result = moduleObject;
        }
      },
      (error) => {
        if (
          (payload as Payload<T>)._status === Status.Pending ||
          payload._status === Status.Uninitialized
        ) {
          const rejected = payload as unknown as RejectedPayload;
          rejected._status = Status.Rejected;
          rejected._result = error;
        }
      },
    );

    if (payload._status === Status.Uninitialized) {
      const pending = payload as unknown as PendingPayload;
      pending._status = Status.Pending;
      pending._result = thenable;
    }
  }

  if (payload._status === Status.Resolved) {
    const moduleObject = payload._result;
    if (__DEV__) {
      if (moduleObject === undefined) {
        console.error(
          "lazy: Expected the result of a dynamic import() call. " +
            "Instead received: %s\n\nYour code should look like: \n  " +
            "const MyComponent = lazy(() => import('./MyComponent'))\n\n" +
            "Did you accidentally put curly braces around the import?",
          moduleObject,
        );
      }
      if (!("default" in moduleObject)) {
        console.error(
          "lazy: Expected the result of a dynamic import() call. " +
            "Instead received: %s\n\nYour code should look like: \n  " +
            "const MyComponent = lazy(() => import('./MyComponent'))",
          moduleObject,
        );
      }
    }
    return moduleObject.default;
  }
  throw payload._result;
}

export function lazy<T>(
  ctor: () => Thenable<{ default: T }>,
): LazyComponent<T, Payload<T>> {
  const payload: Payload<T> = {
    _status: Status.Uninitialized,
    _result: ctor,
  };

  const lazyType: LazyComponent<T, Payload<T>> = {
    $$typeof: REACT_LAZY_TYPE,
    _payload: payload,
    _init: lazyInitializer,
  };

  if (!disableDefaultPropsExceptForClasses && __DEV__) {
    let defaultProps: any;

    Object.defineProperties(lazyType, {
      defaultProps: {
        configurable: true,
        get() {
          return defaultProps;
        },
        set(newDefaultProps: any) {
          console.error(
            "It is not supported to assign `defaultProps` to " +
              "a lazy component import. Either specify them where the component " +
              "is defined, or create a wrapping component around it.",
          );
          defaultProps = newDefaultProps;
          Object.defineProperty(lazyType, "defaultProps", {
            enumerable: true,
          });
        },
      },
    });
  }

  return lazyType;
}

lazy(() => import("./no-repeat-array.js"));

async function delayFor(promise: PromiseLike<void>, delay = 1000) {
  return await new Promise((resolve) => {
    setTimeout(() => resolve(promise), delay);
  });
}

// let r: any
// r({
//   a: 1,
// })
